CIF Time series with LSTM

http://irafm.osu.cz/cif/main.php

Restart for each serie


In [1]:
from __future__ import print_function

import pandas as pd
import numpy as np
import tensorflow as tf

import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (10, 10) 


path='/home/ubuntu/data/training/time_series/'

In [2]:
import os
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]="0"

from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())


[name: "/cpu:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 6844946336710216180
, name: "/gpu:0"
device_type: "GPU"
memory_limit: 10809629082
locality {
  bus_id: 1
}
incarnation: 6981141267824907882
physical_device_desc: "device: 0, name: TITAN X (Pascal), pci bus id: 0000:05:00.0"
]

In [15]:
# Read series
with open(path + 'cif2016_trn.txt') as file:
    values = {}
    forecast={}
    period={}
    for line in file:
        l = line.rstrip().split(";")
        forecast[l[0]] = int(l[1])
        period[l[0]] = l[2]
        values[l[0]] = [float(i) for i in l[3:]]

print(forecast)
print(period)


{'ts1': 12, 'ts2': 12, 'ts3': 12, 'ts4': 12, 'ts5': 12, 'ts6': 12, 'ts7': 12, 'ts8': 12, 'ts9': 12, 'ts10': 12, 'ts11': 12, 'ts12': 12, 'ts13': 12, 'ts14': 12, 'ts15': 12, 'ts16': 12, 'ts17': 12, 'ts18': 12, 'ts19': 12, 'ts20': 12, 'ts21': 12, 'ts22': 12, 'ts23': 12, 'ts24': 12, 'ts25': 12, 'ts26': 12, 'ts27': 12, 'ts28': 12, 'ts29': 12, 'ts30': 12, 'ts31': 12, 'ts32': 12, 'ts33': 12, 'ts34': 12, 'ts35': 12, 'ts36': 12, 'ts37': 12, 'ts38': 12, 'ts39': 12, 'ts40': 12, 'ts41': 12, 'ts42': 12, 'ts43': 12, 'ts44': 12, 'ts45': 12, 'ts46': 12, 'ts47': 12, 'ts48': 12, 'ts49': 6, 'ts50': 6, 'ts51': 12, 'ts52': 12, 'ts53': 12, 'ts54': 6, 'ts55': 6, 'ts56': 6, 'ts57': 6, 'ts58': 6, 'ts59': 12, 'ts60': 6, 'ts61': 12, 'ts62': 12, 'ts63': 12, 'ts64': 12, 'ts65': 6, 'ts66': 12, 'ts67': 6, 'ts68': 6, 'ts69': 6, 'ts70': 6, 'ts71': 6, 'ts72': 6}
{'ts1': 'monthly', 'ts2': 'monthly', 'ts3': 'monthly', 'ts4': 'monthly', 'ts5': 'monthly', 'ts6': 'monthly', 'ts7': 'monthly', 'ts8': 'monthly', 'ts9': 'monthly', 'ts10': 'monthly', 'ts11': 'monthly', 'ts12': 'monthly', 'ts13': 'monthly', 'ts14': 'monthly', 'ts15': 'monthly', 'ts16': 'monthly', 'ts17': 'monthly', 'ts18': 'monthly', 'ts19': 'monthly', 'ts20': 'monthly', 'ts21': 'monthly', 'ts22': 'monthly', 'ts23': 'monthly', 'ts24': 'monthly', 'ts25': 'monthly', 'ts26': 'monthly', 'ts27': 'monthly', 'ts28': 'monthly', 'ts29': 'monthly', 'ts30': 'monthly', 'ts31': 'monthly', 'ts32': 'monthly', 'ts33': 'monthly', 'ts34': 'monthly', 'ts35': 'monthly', 'ts36': 'monthly', 'ts37': 'monthly', 'ts38': 'monthly', 'ts39': 'monthly', 'ts40': 'monthly', 'ts41': 'monthly', 'ts42': 'monthly', 'ts43': 'monthly', 'ts44': 'monthly', 'ts45': 'monthly', 'ts46': 'monthly', 'ts47': 'monthly', 'ts48': 'monthly', 'ts49': 'monthly', 'ts50': 'monthly', 'ts51': 'monthly', 'ts52': 'monthly', 'ts53': 'monthly', 'ts54': 'monthly', 'ts55': 'monthly', 'ts56': 'monthly', 'ts57': 'monthly', 'ts58': 'monthly', 'ts59': 'monthly', 'ts60': 'monthly', 'ts61': 'monthly', 'ts62': 'monthly', 'ts63': 'monthly', 'ts64': 'monthly', 'ts65': 'monthly', 'ts66': 'monthly', 'ts67': 'monthly', 'ts68': 'monthly', 'ts69': 'monthly', 'ts70': 'monthly', 'ts71': 'monthly', 'ts72': 'monthly'}

In [4]:
# Plot the series
plt.rcParams['figure.figsize'] = (10, 40) 

fig = plt.figure()
for i in range(1,len(values)+1):
    fig.add_subplot(len(values)//4,4,i)
    plt.plot(values['ts'+str(i)])


Model each serie with the same LSTM model

  • Restart the notebook if change the serie

In [5]:
# Serie to model
serie='ts71'

In [6]:
# Use 14 historical data to predict
x_length = 14

# Forecast interval
y_length = forecast[serie]

print(x_length, y_length)


# Separate for validation the last 3 cases
num_validation_cases = 3
max_index_train = len(values[serie]) - y_length - x_length - num_validation_cases
max_index_valid = max_index_train + num_validation_cases

# Create data
X_trn = []
X_val = []
y_trn = []
y_val = []
for i in range(max_index_train):
    X_trn += [values[serie][i:i+x_length]]
    y_trn += [values[serie][i+x_length:i+x_length+y_length]]
for i in range(max_index_train, max_index_valid):
    X_val += [values[serie][i:i+x_length]]
    y_val += [values[serie][i+x_length:i+x_length+y_length]]
    
X_trn = np.array(X_trn)
X_val = np.array(X_val)
y_trn = np.array(y_trn)
y_val = np.array(y_val)

print(X_trn.shape, X_val.shape,y_trn.shape, y_val.shape)


14 6
(15, 14) (3, 14) (15, 6) (3, 6)

In [7]:
print(np.max(X_trn),np.max(y_trn))


27872951.542 19280042.602

In [8]:
# Normalize
max_trn = max((np.max(X_trn),np.max(y_trn)))
print('max_trn: ', max_trn)
X_trn = X_trn/max_trn
X_val = X_val/max_trn
y_trn = y_trn/max_trn
y_val = y_val/max_trn


max_trn:  27872951.542

In [9]:
# Model
lstm_feat = 256

gpu_options = tf.GPUOptions(allow_growth = True)
sess = tf.InteractiveSession(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=True))

def dense(x, input_size=10, otput_size=1):
    W = tf.Variable(tf.truncated_normal([input_size, otput_size], stddev=0.1))
    b = tf.Variable(tf.constant(0.1, shape=[otput_size]))
    return tf.matmul(x,W) + b


#Inputs
x_input = tf.placeholder(tf.float32, shape=[None, x_length], name='x')
x_input_lstn = tf.reshape(x_input, [-1, x_length, 1])
y_input = tf.placeholder(tf.float32, shape=[None, y_length], name='y')

keep_prob = tf.placeholder(tf.float32, name='keep_prob')
lstm1 = tf.contrib.rnn.LSTMCell(lstm_feat, initializer=tf.random_uniform_initializer(-0.1, 0.1, seed=123))
lstm1 = tf.contrib.rnn.DropoutWrapper(lstm1, output_keep_prob=keep_prob)
lstm_out, _ = tf.nn.dynamic_rnn(lstm1, x_input_lstn, dtype=tf.float32, scope='lstm16')

#Final dense layer
y_pred = dense(lstm_out[:,-1,:], input_size=lstm_feat, otput_size=y_length)
print(y_pred)

# Loss function
cost  = tf.reduce_sum(tf.square(y_pred - y_input))

numerator = tf.abs(y_pred-y_input)
denominator = tf.divide(tf.abs(y_pred) + tf.abs(y_input), 2)
SMAPE_cost = tf.divide(tf.reduce_sum(tf.divide(numerator, denominator)), y_length)


# Trainer
learning_rate = tf.placeholder(tf.float32, name='learning_rate')
train_step = tf.train.RMSPropOptimizer(learning_rate=learning_rate).minimize(SMAPE_cost)


Tensor("add:0", shape=(?, 6), dtype=float32)

In [10]:
sess.run(tf.global_variables_initializer())

In [11]:
# Train graph
num_epoch=1000
lr=0.001

i=0
for epoch in range(num_epoch):
    feed_dict={x_input: X_trn, y_input: y_trn, learning_rate: lr, keep_prob: 0.9}
    _, c = sess.run([train_step, cost], feed_dict=feed_dict)
    i += 1
    if i%100==0:
        c_tst = cost.eval(feed_dict={x_input: X_val, y_input:  y_val, keep_prob: 1})   
        print('Epoch: ', epoch, ' - LR: ',lr, ' - Cost: ',c, ' - Cost test: ',c_tst )
    lr *= 0.999


Epoch:  99  - LR:  0.0009056978449586675  - Cost:  0.74424  - Cost test:  0.323442
Epoch:  199  - LR:  0.000819468297776412  - Cost:  0.634806  - Cost test:  0.176957
Epoch:  299  - LR:  0.0007414484806367366  - Cost:  0.419203  - Cost test:  0.0646917
Epoch:  399  - LR:  0.0006708567627695095  - Cost:  0.530244  - Cost test:  0.0880383
Epoch:  499  - LR:  0.0006069859307919766  - Cost:  0.376125  - Cost test:  0.107164
Epoch:  599  - LR:  0.0005491961035890855  - Cost:  0.426538  - Cost test:  0.0716826
Epoch:  699  - LR:  0.0004969083217528514  - Cost:  0.323724  - Cost test:  0.142805
Epoch:  799  - LR:  0.0004495987473574321  - Cost:  0.31883  - Cost test:  0.0878993
Epoch:  899  - LR:  0.0004067934159611651  - Cost:  0.321914  - Cost test:  0.124713
Epoch:  999  - LR:  0.00036806348825922246  - Cost:  0.287793  - Cost test:  0.280221

In [12]:
# Evaluate val prediction
y_pred_val = y_pred.eval(feed_dict={x_input: X_val, y_input:  y_val, keep_prob: 1})  
pred_val = np.concatenate((values[serie][:-y_length-1], y_pred_val[-1]*max_trn), axis=0)

plt.rcParams['figure.figsize'] = (10, 3) 
real_vs_pred = np.array([ values[serie][:-1], pred_val]).T
plt.plot(real_vs_pred)


Out[12]:
[<matplotlib.lines.Line2D at 0x7fb7e2b77048>,
 <matplotlib.lines.Line2D at 0x7fb7e2b77208>]

In [13]:
# Evaluate val prediction all validation data
y_pred_val = y_pred.eval(feed_dict={x_input: X_val, y_input:  y_val, keep_prob: 1})  
pred_val = np.concatenate((X_val,y_pred_val), axis=1)
val = np.concatenate((X_val,y_val), axis=1)

plt.rcParams['figure.figsize'] = (10, 10) 
fig = plt.figure()
for i in range(3):
    fig.add_subplot(3,1,i+1)
    real_vs_pred = np.array([ val[i], pred_val[i]]).T
    plt.plot(real_vs_pred)